package com.rxnetwork.bus

import android.util.Log
import rx.Subscriber
import rx.subjects.PublishSubject
import rx.subjects.SerializedSubject
import rx.subjects.Subject
import rx.subscriptions.CompositeSubscription
import java.lang.reflect.ParameterizedType
import java.util.*

/**
 * by xiaocode
 */
class RxBus private constructor() {

    private val rxMap: MutableMap<Any, Subject<Any, Any>>
    private val compositeSubscription: CompositeSubscription

    init {
        rxMap = HashMap<Any, Subject<Any, Any>>()
        compositeSubscription = CompositeSubscription()
    }

    /**
     * 发送一个带tag,但不携带信息的消息

     * @param tag 标志
     */
    fun send(tag: Any) {
        send(tag, tag)
    }

    /**
     * 发送一个带tag,携带信息的消息
     * @param tag     标志
     * *
     * @param message 内容
     */
    fun send(tag: Any,
             message: Any = tag) {
        if (rxMap.containsKey(tag)) {
            Log.i(tag as String, "发送消息")
            rxMap[tag]?.onNext(message)
        }
    }

    /**
     * 接受消息

     * @param tag         标志
     * *
     * @param callBack<T> 回调 T 消息实体类型
    </T> */
    fun <T> toSubscription(tag: Any, callBack: RxBusCallBack<T>) {
        var subject = rxMap[tag]
        if (subject == null) {
            subject = SerializedSubject(PublishSubject.create<Any>())
            rxMap.put(tag, subject)
        }
        compositeSubscription.add(subject
                ?.ofType((callBack.javaClass.genericInterfaces[0] as ParameterizedType).actualTypeArguments[0] as Class<T>)
                //                .ofType((Class<T>) ((ParameterizedType) callBack.getClass().getGenericSuperclass()).getActualTypeArguments()[0])
                ?.subscribe(
                        object : RxBusSubscriber<T>() {
                            override fun onError(e: Throwable) {
                                super.onError(e)
                                callBack.onError(e)
                            }

                            override fun onNext(t: T) {
                                super.onNext(t)
                                callBack.onNext(t)
                            }
                        }))

    }


    /**
     * 取消订阅

     * @param tag 标志
     */
    fun unregister(tag: Any) {
        if (rxMap.containsKey(tag)) {
            rxMap.remove(tag)
        }
    }

    /**
     * 取消所有订阅
     */
    fun unregisterAll() {
        if (!compositeSubscription.isUnsubscribed) {
            compositeSubscription.clear()
        }
        rxMap.clear()
    }

    private open class RxBusSubscriber<T> : Subscriber<T>() {

        override fun onCompleted() {

        }

        override fun onError(e: Throwable) {

        }

        override fun onNext(t: T) {

        }
    }

    companion object {
        private var rxBus: RxBus? = null

        val instance: RxBus
            get() {
                if (rxBus == null) {
                    synchronized(RxBus::class.java) {
                        if (rxBus == null) {
                            rxBus = RxBus()
                        }
                    }
                }
                return rxBus as RxBus
            }
    }
}